package cn.schoolwow.workflow.module.instance.action.flow.start;

import cn.schoolwow.quickdao.domain.DAO;
import cn.schoolwow.quickdao.domain.transaction.Transaction;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.check.instance.CheckInstance;
import cn.schoolwow.workflow.domain.instance.StartWorkFlowRequest;
import cn.schoolwow.workflow.domain.instance.WorkFlowInstanceStatus;
import cn.schoolwow.workflow.domain.task.TaskType;
import cn.schoolwow.workflow.entity.WorkFlowDefinition;
import cn.schoolwow.workflow.entity.WorkFlowInstance;
import cn.schoolwow.workflow.entity.WorkFlowInstanceCarbonCopy;
import cn.schoolwow.workflow.entity.WorkFlowNode;
import cn.schoolwow.workflow.module.common.domain.QuickWorkFlowOption;
import cn.schoolwow.workflow.module.common.flow.AddWorkFlowHistoryFlow;
import cn.schoolwow.workflow.module.task.action.domain.CompleteTaskOption;
import cn.schoolwow.workflow.module.task.action.flow.complete.transaction.InsertWorkFlowTaskFlow;
import cn.schoolwow.workflow.module.task.action.flow.complete.transaction.UpdateWorkFlowInstanceAndTaskFlow;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class StartWorkFlowTransactionFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        DAO dao = flowContext.checkInstanceData(DAO.class);

        //保存工作流实例和查询任务分成两个事务进行
        dao.startTransaction(transaction -> {
            flowContext.putTemporaryInstanceData(transaction, Transaction.class);
            insertWorkFlowInstance(flowContext);
            insertCarbonCopy(flowContext);
            executeAfterInstanceCreateListener(flowContext);
        });

        dao.startTransaction(transaction -> {
            flowContext.putTemporaryInstanceData(transaction, Transaction.class);
            flowContext.startFlow(new InsertWorkFlowTaskFlow())
                    .next(new UpdateWorkFlowInstanceAndTaskFlow())
                    .putCurrentCompositeFlowInstanceData(TaskType.COMPLETE)
                    .putTemporaryInstanceData(new CompleteTaskOption())
                    .execute();
        });
    }

    @Override
    public String name() {
        return "启动工作流-事务操作";
    }

    private void insertWorkFlowInstance(FlowContext flowContext){
        WorkFlowDefinition workFlowDefinition = flowContext.checkInstanceData(WorkFlowDefinition.class);
        WorkFlowNode nextNode = flowContext.checkData("nextNode", WorkFlowNode.class);
        StartWorkFlowRequest startWorkFlowRequest = flowContext.checkInstanceData(StartWorkFlowRequest.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        transaction.addRecordString("插入工作流实例信息");
        WorkFlowInstance workFlowInstance = new WorkFlowInstance();
        workFlowInstance.setDefinitionId(workFlowDefinition.getId());
        workFlowInstance.setName(startWorkFlowRequest.instanceName);
        workFlowInstance.setWorkFlowNodeId(nextNode.getId());
        workFlowInstance.setInitiator(startWorkFlowRequest.initiator);
        workFlowInstance.setContextData(startWorkFlowRequest.contextData);
        workFlowInstance.setStatus(WorkFlowInstanceStatus.Running.status);
        JSONObject meta = new JSONObject();
        meta.put("manualWorkFlowAssignerList", startWorkFlowRequest.manualWorkFlowAssignerList);
        workFlowInstance.setMeta(meta);
        transaction.insert(workFlowInstance);

        flowContext.putCurrentFlowInstanceData(workFlowInstance);
    }

    private void insertCarbonCopy(FlowContext flowContext){
        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        StartWorkFlowRequest startWorkFlowRequest = flowContext.checkInstanceData(StartWorkFlowRequest.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        CheckInstance.newCheck()
                .idFieldCheck(workFlowInstance.getId(), "工作流实例id");

        flowContext.putInstanceData(workFlowInstance);

        transaction.addRecordString("插入工作流实例抄送列表信息");
        List<WorkFlowInstanceCarbonCopy> workFlowInstanceCarbonCopyList = new ArrayList<>();
        for(String carbonCopy:startWorkFlowRequest.carbonCopyList){
            WorkFlowInstanceCarbonCopy workFlowInstanceCarbonCopy = new WorkFlowInstanceCarbonCopy();
            workFlowInstanceCarbonCopy.setInstanceId(workFlowInstance.getId());
            workFlowInstanceCarbonCopy.setCarbonCopy(carbonCopy);
            workFlowInstanceCarbonCopyList.add(workFlowInstanceCarbonCopy);
        }
        transaction.insertIgnore(workFlowInstanceCarbonCopyList);

        flowContext.startFlow(new AddWorkFlowHistoryFlow())
                .putCurrentCompositeFlowData("message", "启动工作流实例")
                .putCurrentCompositeFlowData("assigner", startWorkFlowRequest.initiator)
                .execute();
    }

    private void executeAfterInstanceCreateListener(FlowContext flowContext){
        QuickWorkFlowOption quickWorkFlowOption = flowContext.checkInstanceData(QuickWorkFlowOption.class);

        if(null==quickWorkFlowOption.workFlowInstanceListener){
            return;
        }
        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        quickWorkFlowOption.workFlowInstanceListener.afterInstanceCreate(workFlowInstance);
    }

}
